using System;
using GOAP.Other;
using System.Text;
using System.Collections.Generic;

namespace GOAP.Core
{
    public interface IState
    {
        void Set(string key, bool value);
        void Set(State key);
        bool Get(string key);
        void AddStateChangeListener(Action<bool> action);
        ICollection<string> GetKeys();
        bool ContainKey(string key);
        bool ContainState(IState other);
        void Clear();
    }

    public class State : IState
    {
        /// <summary>
        /// 数据映射
        /// </summary>
        private Dictionary<string, bool> _dataTable;
        /// <summary>
        /// 事件改变回调
        /// </summary>
        private Action<bool> _onChange;

        public State()
        {
            _dataTable = new Dictionary<string, bool>();
        }

        /// <summary>
        /// 设置状态
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public void Set(string key, bool value)
        {
            if (_dataTable.ContainsKey(key) && _dataTable[key] != value)
            {
                ChangeValue(key, value);
            }
            else if (!_dataTable.ContainsKey(key))
            {
                ChangeValue(key, value);
            }
        }

        /// <summary>
        /// 设置状态
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public void Set(State other)
        {
            foreach (var key in other.GetKeys())
            {
                Set(key, other.Get(key));
            }
        }

        /// <summary>
        /// 获取全部键值
        /// </summary>
        /// <returns></returns>
        public ICollection<string> GetKeys()
        {
            return _dataTable.Keys;
        }

        /// <summary>
        /// 修改状态
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        private void ChangeValue(string key, bool value)
        {
            _dataTable[key] = value;
            if (_onChange != null) _onChange(value);
        }

        /// <summary>
        /// 添加状态改变回调
        /// </summary>
        /// <param name="onChange"></param>
        public void AddStateChangeListener(Action<bool> onChange)
        {
            _onChange = onChange;
        }


        /// <summary>
        /// 获取状态
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public bool Get(string key)
        {
            if (!_dataTable.ContainsKey(key))
            {
                Logger.Error("当前状态不存在此键值," + key);
                return false;
            }
            else
            {
                return _dataTable[key];
            }
        }

        /// <summary>
        /// 检测当前状态是否包含一个键值
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public bool ContainKey(string key)
        {
            return _dataTable.ContainsKey(key);
        }

        /// <summary>
        /// 检测当前状态是否包含另一个状态
        /// </summary>
        /// <param name="other"></param>
        /// <returns></returns>
        public bool ContainState(IState other)
        {
            foreach (var key in other.GetKeys())
            {
                if (!ContainKey(key) || _dataTable[key] != other.Get(key))
                    return false;
            }
            return true;
        }

        /// <summary>
        /// 清除当前状态
        /// </summary>
        public void Clear()
        {
            _dataTable.Clear();
        }

        /// <summary>
        /// 将数据转换为字符串
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("{");
            foreach (var data in _dataTable)
            {
                sb.Append(data.Key);
                sb.Append(":");
                sb.Append(_dataTable[data.Key]);
                sb.Append(",");
            }
            sb.Remove(sb.Length - 1, 1);
            sb.Append("}");
            return sb.ToString();
        }
    }

    public class State<TKey> : State where TKey : Enum
    {
        public State() : base() { }

        /// <summary>
        /// 设置状态
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public void Set(TKey key, bool value)
        {
            base.Set(key.ToString(), value);
        }

        /// <summary>
        /// 获取状态
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public bool Get(TKey key)
        {
            return base.Get(key.ToString());
        }

        /// <summary>
        /// 检测当前状态是否包含一个键值
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public bool ContainKey(TKey key)
        {
            return base.ContainKey(key.ToString());
        }
    }
}